/**
 * 演示一个过程宏的实现
 * 其中关联文档
 * 1. syn  的 DeriveInput 结构  --  https://docs.rs/syn/1.0.109/syn/struct.DeriveInput.html
 * 2. quote crate 的quote! 宏   -- https://docs.rs/quote/latest/quote/
 */

use proc_macro::TokenStream;
use quote::quote;
/**
 * 这是一个过程宏的典型实现，按照书本的阐述，大部分的过程宏的实现结构基本同此
 * 1. 解析输入的代码
 * 2. 基于解析的数据结构构建 trait 实现
 * 下面的sysn::parse(input).unwrap() 就是第一步,它产生的结构大体如下：
 * DeriveInput {
            // --snip--

            ident: Ident {
                ident: "Pancakes",
                span: #0 bytes(95..103)
            },
            data: Struct(
                DataStruct {
                    struct_token: Struct,
                    fields: Unit,
                    semi_token: Some(
                        Semi
                    )
                }
            )
        }
 */
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    //1.使用syn crate 将字符串中的 Rust 代码解析成为一个可以操作的数据结构
    let ast = syn::parse(input).unwrap();

    //2.步骤2- Build the trait implementation
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    // 使用quote!宏构建最终的trait实现
    let gen = quote! {
        impl Hello for #name {
            fn hello_macro() {
                println!("Hello, Macro! My name is {}!", stringify!(#name));
            }

            fn showme(&self)->String{
                self.name.clone()+"[年龄:"+self.age.to_string().as_str()+"]"
            }
            fn get_name(&self)->String{
                self.name.clone()
            }
        }
    };
    gen.into()
}